using System;
using NUnit.Framework;

namespace ValidationFramework.Tests
{
    [TestFixture]
    public class CustomRuleAttributeTest
    {
        private const string expectedTypeName = "ValidationFramework.Tests.CustomRuleTest+ValidationClass,ValidationFramework.Tests";
        private const string expectedMethodName = "ValidateValid";
        private const string expectedRuleInterpretation = "expectedRuleInterpretation";

  
        [Test]
        public void CheckValuesType()
        {
            var ruleAttribute = new CustomRuleAttribute(typeof(CustomRuleTest.ValidationClass), expectedMethodName, expectedRuleInterpretation);
            Assert.AreEqual(typeof(CustomRuleTest.ValidationClass), ruleAttribute.ValidationType);
            Assert.AreEqual(expectedMethodName, ruleAttribute.ValidationMethod);
            Assert.AreEqual(expectedRuleInterpretation, ruleAttribute.RuleInterpretation);

            var propertyRule = (CustomRule)ruleAttribute.CreateRule(new MockPropertyDescriptor<object>("foo"));
            var parameterRule = (CustomRule)ruleAttribute.CreateRule(new MockParameterDescriptor<object>("foo"));

            Assert.AreEqual(typeof(CustomRuleTest.ValidationClass).GetMethod("ValidateValid"), propertyRule.Handler.Method);
            Assert.AreEqual(expectedRuleInterpretation, propertyRule.RuleInterpretation);

            Assert.AreEqual(typeof(CustomRuleTest.ValidationClass).GetMethod("ValidateValid"), parameterRule.Handler.Method);
            Assert.AreEqual(expectedRuleInterpretation, parameterRule.RuleInterpretation);

        }
  
        [Test]
        public void CheckValuesString()
        {
            var ruleAttribute = new CustomRuleAttribute(expectedTypeName, expectedMethodName, expectedRuleInterpretation);
            Assert.AreEqual(typeof(CustomRuleTest.ValidationClass), ruleAttribute.ValidationType);
            Assert.AreEqual(expectedMethodName, ruleAttribute.ValidationMethod);
            Assert.AreEqual(expectedRuleInterpretation, ruleAttribute.RuleInterpretation);

            var propertyRule = (CustomRule)ruleAttribute.CreateRule(new MockPropertyDescriptor<object>("foo"));
            var parameterRule = (CustomRule)ruleAttribute.CreateRule(new MockParameterDescriptor<object>("foo"));

            Assert.AreEqual(typeof(CustomRuleTest.ValidationClass).GetMethod("ValidateValid"), propertyRule.Handler.Method);
            Assert.AreEqual(expectedRuleInterpretation, propertyRule.RuleInterpretation);

            Assert.AreEqual(typeof(CustomRuleTest.ValidationClass).GetMethod("ValidateValid"), parameterRule.Handler.Method);
            Assert.AreEqual(expectedRuleInterpretation, parameterRule.RuleInterpretation);

        }
        
        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void ExceptionInvalidType()
        {
            new CustomRuleAttribute("InvalidType", expectedMethodName, expectedRuleInterpretation);
        }


        [Test]
        public void CallAttributeTester()
        {
            AttributeTester.CheckDefaultValues<object>(new CustomRuleAttribute(expectedTypeName, expectedMethodName, expectedRuleInterpretation), true, true);
            AttributeTester.CheckNonDefaultValues<object>(new CustomRuleAttribute(expectedTypeName, expectedMethodName, expectedRuleInterpretation), true, true);
            AttributeTester.CheckDefaultValues<object>(new CustomRuleAttribute(typeof(CustomRuleTest.ValidationClass), expectedMethodName, expectedRuleInterpretation), true, true);
            AttributeTester.CheckNonDefaultValues<object>(new CustomRuleAttribute(typeof(CustomRuleTest.ValidationClass), expectedMethodName, expectedRuleInterpretation), true, true);
        }

    }
}